#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <assert.h>

#include "utility.h"
#define BUF_SIZE 4096

int main(int argc, char *argv[])
{
    // 打开文件
    int fd = open(SHR_STRU, O_RDWR | O_CREAT, 0777);
    UTIL_ASSERT(fd!=-1);

    // 获取设置文件大小
    off_t pageSize = sysconf(_SC_PAGE_SIZE);
    off_t length = sizeof(SHARE_HEAD);
    length = (length + pageSize - 1) & ~(pageSize - 1);
    int ret = ftruncate(fd, length); /* To obtain file size */
    UTIL_ASSERT(fd!=-1);

    // 映射结构体
    volatile SHARE_HEAD *pHead = (volatile SHARE_HEAD *)mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    assert(pHead != MAP_FAILED);
    close(fd);

    // 映射地址
    fd = open(SHR_FILE_BUF, O_RDWR | O_CREAT, 0777);
    assert(fd != -1);
    ret = ftruncate(fd, SHR_BUF_LEN); /* To obtain file size */
    assert(ret != -1);
    pHead->pAddr1 = (volatile char *)mmap(NULL, SHR_BUF_LEN, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    assert(pHead->pAddr1 != NULL);
    close(fd);

    fd = open("./direct_io.data", O_WRONLY | O_CREAT | O_DIRECT, 0755);
    UTIL_ASSERT(fd!=-1);

    if (pHead->ridx != pHead->widx)
    {
        length = (pHead->widx + pHead->totalLen - pHead->ridx) % pHead->totalLen;
        length = (length) & ~(pageSize - 1);
        ret = write(fd, (const void *)(pHead->pAddr1+4096), length-4096);
        if (ret == -1)
        {
            printf("%s#%d,write failed,addr[%p],errno(%d):[%s]\n", __FUNCTION__, __LINE__, pHead->pAddr1, errno, strerror(errno));
        }
        else
        {
            printf("%s#%d,write success\n", __FUNCTION__, __LINE__);
            pHead->ridx += ret;
        }
    }
    unsigned char *buf;
    ret = posix_memalign((void **)&buf, pageSize, length);
    UTIL_ASSERT(ret == 0);
    ret = write(fd, (const void *)buf, length);
    if (ret == -1)
    {
        printf("%s#%d,write failed,addr[%p],errno(%d):[%s]\n", __FUNCTION__, __LINE__, buf, errno, strerror(errno));
    }
    else
    {
        printf("%s#%d,write buf success\n", __FUNCTION__, __LINE__);
    }

    close(fd);
    return 0;
}